package visitors

import (
	"context"
	"encoding/json"
	"errors"
	"log"
	"time"
	"wave-service/server/app/common/im"
	"wave-service/server/app/common/response"
	"wave-service/server/app/models"

	"wave-service/server/app/internal/svc"
	"wave-service/server/app/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type VisitorInfoLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewVisitorInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *VisitorInfoLogic {
	return &VisitorInfoLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *VisitorInfoLogic) getVisitorContacts(uid int64) (err error, hasId int64, channelId string) {
	adminId, ad_err := l.svcCtx.VisitorsModel.FindByAdminId(l.ctx)
	if ad_err != nil {
		logx.Errorf("%d获得对应客服关系失败 %v", ad_err.Error())
		return errors.New("未获得对应客服"), 0, ""
	}
	hasId = adminId
	log.Printf("uid=%d 获得客服对应关系%d", uid, hasId)
	channelId = im.GenChannelIdByContact(uid, hasId, l.svcCtx.Config.Auth.AccessSecret)
	contact := models.CusVisitorContacts{
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
		VisitorId: uid,
		HasId:     hasId,
		ChannelId: channelId,
		Status:    1,
	}
	_, _err := l.svcCtx.VisitorContactsModel.Insert(l.ctx, &contact)
	if _err != nil {
		logx.Errorf("%d插入对应客服关系失败 %v", uid, _err.Error())
		return errors.New("插入对应客服关系失败"), 0, ""
	}

	return nil, hasId, channelId
}

func (l *VisitorInfoLogic) VisitorInfo(req *types.VisitorInfoRequest) (resp *types.VisitorInfoResponse, err error) {
	uid, _ := l.ctx.Value("uid").(json.Number).Int64()
	log.Println("用户ID=", l.ctx.Value("uid"))
	user, err := l.svcCtx.VisitorsModel.FindOne(l.ctx, uid)
	if err != nil {
		logx.Errorf("获得用户信息失败%v", err.Error())
		return nil, response.Error(500, "系统错误")
	}
	log.Println("用户信息：", user)
	// 查找是否已有对应客服关系
	userContact, ucErr := l.svcCtx.VisitorContactsModel.FindOneByUserId(l.ctx, uid)
	log.Println("查找是否已有对应客服err=", ucErr)
	var hasId int64
	var channelId string
	if ucErr == models.ErrNotFound {
		log.Println("去获得关系")
		err, hasId, channelId = l.getVisitorContacts(uid)
		if err != nil {
			return nil, response.Error(500, err.Error())
		}
	} else if ucErr != nil {
		logx.Errorf("%d获取对应客服关系失败 %v", uid, ucErr.Error())
		return nil, response.Error(500, "获取对应客服关系失败")
	} else {
		// 检查客服是否在线
		custcare, err := l.svcCtx.VisitorsModel.FindOne(l.ctx, userContact.HasId)
		if err != nil {
			log.Println("获得客服信息失败", err.Error())
			logx.Errorf("获得客服信息失败%v", err.Error())
			return nil, response.Error(500, "系统错误")
		}
		log.Println("客服是否在线=", custcare.Online)
		if custcare.Online == 0 {
			err, hasId, channelId = l.getVisitorContacts(uid)
			if err != nil {
				return nil, response.Error(500, err.Error())
			}
			l.svcCtx.VisitorContactsModel.UpdateStatus(l.ctx, userContact.Id, 2)
		} else {
			hasId = userContact.HasId
			channelId = userContact.ChannelId
		}
	}

	toUser, err := l.svcCtx.VisitorsModel.FindOne(l.ctx, hasId)
	if err != nil {
		logx.Errorf("%d用户获取对应客服信息失败 %v", uid, err.Error())
		return nil, response.Error(500, "系统错误")
	}

	// 请求次数添加
	detail, err := l.svcCtx.VisitorDetailsModel.FindOneByVisitorId(l.ctx, uid)
	if err != nil {
		logx.Errorf("%d获得用户详情失败 %v", uid, err.Error())
		return nil, response.Error(500, "获得用户详情失败")
	}
	detail.Visits = detail.Visits + 1
	err = l.svcCtx.VisitorDetailsModel.Update(l.ctx, detail)
	if err != nil {
		logx.Errorf("uid=%v 用户点击率更新失败 %v", uid, err.Error())
		return nil, response.Error(500, "用户点击率更新失败")
	}

	// 检查是否在ip黑名单里
	ipblack, ipErr := l.svcCtx.IpBlacklistsModel.FindOneByIp(l.ctx, user.ClientIp)
	if ipErr != models.ErrNotFound {
		if ipErr != nil {
			log.Println("ip黑名单错误", ipErr)
		}
		if ipblack.Ip != "" {
			if ipblack.Status == 1 {
				// 在IP黑名单里
				return nil, response.Error(600, "对不起，您在IP黑名单里！")
			}
		}
	}

	return &types.VisitorInfoResponse{
		Uuid:          user.Uuid,
		Nickname:      user.Nickname,
		Avatar:        user.Avatar,
		ClientIp:      user.ClientIp,
		City:          user.City,
		CreateAt:      user.CreatedAt.String(),
		ChannelId:     channelId,
		ServiceUuid:   toUser.Uuid,
		ServiceName:   toUser.Nickname,
		ServiceAvatar: toUser.Avatar,
	}, nil
}
